using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Collections.Specialized;
using System.Windows.Data;

namespace GMUtilitiesDotNet.Gestures
{
    /// <summary>
    /// This represents a single guesture to command mapping.  
    /// It derives from Freezable in order to inherit context and support 
    /// element name bindings per Mike Hillberg blog post.
    /// </summary>
    public class GestureCommand : Freezable
    {
        #region Dependency properties
        #region Command DP
        /// <summary>
        /// Command Property Dependency Property
        /// </summary>
        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.Register( "Command", typeof( ICommand ),
            typeof( GestureCommand ), new UIPropertyMetadata( null ) );

        /// <summary>
        /// Gets or sets the Command property. 
        /// </summary>
        public ICommand Command
        {
            get { return (ICommand) GetValue( CommandProperty ); }
            set { SetValue( CommandProperty, value ); }
        }
        #endregion

        #region Gesture DP
        /// <summary>
        /// Gesture Dependency Property
        /// </summary>
        public static readonly DependencyProperty GestureProperty =
            DependencyProperty.Register( "Gesture", typeof( IGesture ), typeof( GestureCommand ),
            new UIPropertyMetadata( null ) );

        public IGesture Gesture
        {
            get { return (IGesture) GetValue( GestureProperty ); }
            set { SetValue( GestureProperty, value ); }
        }
        #endregion

        #region DataContext DP
        /// <summary>
        /// DataContext for any bindings applied to this CommandEvent
        /// </summary>
        public static readonly DependencyProperty DataContextProperty =
            FrameworkElement.DataContextProperty.AddOwner( typeof( GestureCommand ),
            new FrameworkPropertyMetadata( null ) );
        #endregion
        #endregion

        /// <summary>
        /// Executes gesture event and optionally executes corresponding command.
        /// </summary>
        /// <param name="gestureHandler">Handler to handle specific gesture event</param>
        /// <returns>True if gesture has handled gesture event</returns>
        public bool TestGesture(Predicate<IGesture> gestureHandler)
        {
            bool isHandled = false;

            // Test gesture only if command is assigned and command can execute.
            // When command is not assigned or can not execute, input actions are not
            // handled by that gesture.
            if (Command != null && Command.CanExecute(null))
            {
                bool shouldExecuteCommand = gestureHandler(Gesture);

                isHandled |= Gesture.Handled;

                if (shouldExecuteCommand)
                {
                    Command.Execute(Gesture.CommandParam);
                    Gesture.Reset();
                }
            }

            return isHandled;
        }

        #region Overrides
        /// <summary>
        /// When implemented in a derived class, creates a new instance of the <see cref="T:System.Windows.Freezable"/> derived class. 
        /// </summary>
        /// <returns>
        /// The new instance.
        /// </returns>
        protected override Freezable CreateInstanceCore()
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}
